{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "fb0ebaf1",
   "metadata": {},
   "source": [
    "[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/langchain-ai/langchain-academy/blob/main/module-2/trim-filter-messages.ipynb) [![Open in LangChain Academy](https://cdn.prod.website-files.com/65b8cd72835ceeacd4449a53/66e9eba12c7b7688aa3dbb5e_LCA-badge-green.svg)](https://academy.langchain.com/courses/take/intro-to-langgraph/lessons/58239435-lesson-4-trim-and-filter-messages)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c52ea2f9-03ff-4647-b782-46867ebed04e",
   "metadata": {},
   "source": [
    "# Filtering and trimming messages\n",
    "\n",
    "## Review\n",
    "\n",
    "Now, we have a deeper understanding of a few things: \n",
    "\n",
    "* How to customize the graph state schema\n",
    "* How to define custom state reducers\n",
    "* How to use multiple graph state schemas\n",
    "\n",
    "## Goals\n",
    "\n",
    "Now, we can start using these concepts with models in LangGraph!\n",
    " \n",
    "In the next few sessions, we'll build towards a chatbot that has long-term memory.\n",
    "\n",
    "Because our chatbot will use messages, let's first talk a bit more about advanced ways to work with messages in graph state."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d5197aba-5d46-421b-ae3b-4e3034edcfda",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%capture --no-stderr\n",
    "%pip install --quiet -U langchain_core langgraph langchain_openai"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "768dc606-d5f2-468d-96ea-910b264e0f8a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "OPENAI_API_KEY:  ········\n"
     ]
    }
   ],
   "source": [
    "import os, getpass\n",
    "\n",
    "def _set_env(var: str):\n",
    "    if not os.environ.get(var):\n",
    "        os.environ[var] = getpass.getpass(f\"{var}: \")\n",
    "\n",
    "_set_env(\"OPENAI_API_KEY\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8b64d8d3-e4ac-4961-bdc0-688825eb5864",
   "metadata": {},
   "source": [
    "We'll use [LangSmith](https://docs.smith.langchain.com/) for [tracing](https://docs.smith.langchain.com/concepts/tracing).\n",
    "\n",
    "We'll log to a project, `langchain-academy`. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "dd020c79",
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "LANGCHAIN_API_KEY:  ········\n"
     ]
    }
   ],
   "source": [
    "_set_env(\"LANGCHAIN_API_KEY\")\n",
    "os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\n",
    "os.environ[\"LANGCHAIN_PROJECT\"] = \"langchain-academy\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "72f3fc90-58b6-4f7f-897e-dddf6ae532c7",
   "metadata": {},
   "source": [
    "## Messages as state\n",
    "\n",
    "First, let's define some messages."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "cf11a463-e27a-4a05-b41d-64882e38edca",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: Bot\n",
      "\n",
      "So you said you were researching ocean mammals?\n",
      "================================\u001b[1m Human Message \u001b[0m=================================\n",
      "Name: Lance\n",
      "\n",
      "Yes, I know about whales. But what others should I learn about?\n"
     ]
    }
   ],
   "source": [
    "from pprint import pprint\n",
    "from langchain_core.messages import AIMessage, HumanMessage\n",
    "messages = [AIMessage(f\"So you said you were researching ocean mammals?\", name=\"Bot\")]\n",
    "messages.append(HumanMessage(f\"Yes, I know about whales. But what others should I learn about?\", name=\"Lance\"))\n",
    "\n",
    "for m in messages:\n",
    "    m.pretty_print()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b814adcb-6bf9-4b75-be11-e59f933fbd0c",
   "metadata": {},
   "source": [
    "Recall we can pass them to a chat model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "4712e288-e622-48a2-ad3f-a52f65f3ab08",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='In addition to whales, there are several other fascinating ocean mammals that you might want to explore:\\n\\n1. **Dolphins** - Known for their intelligence and social behavior, dolphins are found in oceans around the world. There are about 90 different species, including the well-known bottlenose dolphin.\\n\\n2. **Porpoises** - Often confused with dolphins, porpoises are smaller and have distinctively rounded faces and flat, spade-shaped teeth. The harbor porpoise is one of the most common species.\\n\\n3. **Seals** - There are many species of seals, often categorized into earless seals (true seals) and eared seals (including sea lions and fur seals). Harp seals and elephant seals are notable examples.\\n\\n4. **Sea Lions** - Known for their external ear flaps and the ability to \"walk\" on land using their large flippers, sea lions are often seen in coastal waters.\\n\\n5. **Walruses** - These large marine mammals are known for their tusks and are typically found in Arctic regions. They primarily feed on mollusks.\\n\\n6. **Manatees and Dugongs** - Often referred to as “sea cows,” these gentle herbivores graze on sea grasses and can be found in warm coastal waters.\\n\\n7. **Otters** - Although not exclusively marine, sea otters spend most of their time in the ocean and are known for their use of tools to open shells.\\n\\n8. **Polar Bears** - While primarily land animals, polar bears are excellent swimmers and spend much of their life on the sea ice hunting for seals.\\n\\n9. **Narwhals** - Known as the \"unicorn of the sea,\" narwhals are toothed whales known for the long, spiral tusk that protrudes from the head of males.\\n\\n10. **Orcas (Killer Whales)** - Actually the largest members of the dolphin family, orcas are apex predators and are found in oceans all over the world.\\n\\nThese mammals play crucial roles in their ecosystems and exhibit fascinating behaviors and adaptations that are well worth studying.', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 427, 'prompt_tokens': 39, 'total_tokens': 466, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_eb9dce56a8', 'finish_reason': 'stop', 'logprobs': None}, id='run-bf7afacb-049f-4c1d-b52a-003a9d1900bd-0', usage_metadata={'input_tokens': 39, 'output_tokens': 427, 'total_tokens': 466, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain_openai import ChatOpenAI\n",
    "llm = ChatOpenAI(model=\"gpt-4o\")\n",
    "llm.invoke(messages)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fbd1dab8-0af8-4621-8264-ce65065f76ec",
   "metadata": {},
   "source": [
    "We can run our chat model in a simple graph with `MessagesState`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "bbd8c39c-633b-4176-9cc6-8318e42bb5dd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from IPython.display import Image, display\n",
    "from langgraph.graph import MessagesState\n",
    "from langgraph.graph import StateGraph, START, END\n",
    "\n",
    "# Node\n",
    "def chat_model_node(state: MessagesState):\n",
    "    return {\"messages\": llm.invoke(state[\"messages\"])}\n",
    "\n",
    "# Build graph\n",
    "builder = StateGraph(MessagesState)\n",
    "builder.add_node(\"chat_model\", chat_model_node)\n",
    "builder.add_edge(START, \"chat_model\")\n",
    "builder.add_edge(\"chat_model\", END)\n",
    "graph = builder.compile()\n",
    "\n",
    "# View\n",
    "display(Image(graph.get_graph().draw_mermaid_png()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "3a5a3e4a-ccfd-4d14-81f1-f0de6e11a1e4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: Bot\n",
      "\n",
      "So you said you were researching ocean mammals?\n",
      "================================\u001b[1m Human Message \u001b[0m=================================\n",
      "Name: Lance\n",
      "\n",
      "Yes, I know about whales. But what others should I learn about?\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "\n",
      "In addition to whales, there are many fascinating ocean mammals you might want to learn about. Here are some notable ones:\n",
      "\n",
      "1. **Dolphins**: These intelligent creatures are part of the cetacean family, like whales, and are known for their playful behavior and advanced communication skills.\n",
      "\n",
      "2. **Porpoises**: Similar to dolphins but generally smaller and with different facial features and teeth. They are also very intelligent but less studied than dolphins.\n",
      "\n",
      "3. **Seals**: These pinnipeds are known for their distinctive looks, with their streamlined bodies and flippers suited for swimming. There are 33 species, including the harbor seal and the gray seal.\n",
      "\n",
      "4. **Sea Lions**: Often confused with seals, sea lions are more social and agile on land due to their ability to rotate their hind flippers forward for walking.\n",
      "\n",
      "5. **Walruses**: Recognizable by their long tusks and massive bodies, walruses are social animals that often congregate in large groups.\n",
      "\n",
      "6. **Manatees**: Often called sea cows, these large, gentle herbivores inhabit warm coastal waters and are known for their slow movements and grazing habits.\n",
      "\n",
      "7. **Dugongs**: Similar to manatees, they predominantly inhabit the waters of the Indo-Pacific and are also herbivorous.\n",
      "\n",
      "8. **Sea Otters**: Though smaller and not fully aquatic, they're fascinating for their use of tools and their role in maintaining healthy kelp forest ecosystems.\n",
      "\n",
      "9. **Polar Bears**: Considered marine mammals due to their dependence on the sea, primarily as they hunt seals on sea ice.\n",
      "\n",
      "Each of these mammals has unique adaptations and behaviors that make them fascinating subjects of study, connecting them to the diverse and complex ecosystems of the oceans.\n"
     ]
    }
   ],
   "source": [
    "output = graph.invoke({'messages': messages})\n",
    "for m in output['messages']:\n",
    "    m.pretty_print()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "34c33e63-1ef4-412d-bb10-6a1b9e5b35a7",
   "metadata": {},
   "source": [
    "## Reducer\n",
    "\n",
    "A practical challenge when working with messages is managing long-running conversations. \n",
    "\n",
    "Long-running conversations result in high token usage and latency if we are not careful, because we pass a growing list of messages to the model.\n",
    "\n",
    "We have a few ways to address this.\n",
    "\n",
    "First, recall the trick we saw using `RemoveMessage` and the `add_messages` reducer."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "222c6bc5-bb0e-4a43-80f5-c8ec38d99f3a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from langchain_core.messages import RemoveMessage\n",
    "\n",
    "# Nodes\n",
    "def filter_messages(state: MessagesState):\n",
    "    # Delete all but the 2 most recent messages\n",
    "    delete_messages = [RemoveMessage(id=m.id) for m in state[\"messages\"][:-2]]\n",
    "    return {\"messages\": delete_messages}\n",
    "\n",
    "def chat_model_node(state: MessagesState):    \n",
    "    return {\"messages\": [llm.invoke(state[\"messages\"])]}\n",
    "\n",
    "# Build graph\n",
    "builder = StateGraph(MessagesState)\n",
    "builder.add_node(\"filter\", filter_messages)\n",
    "builder.add_node(\"chat_model\", chat_model_node)\n",
    "builder.add_edge(START, \"filter\")\n",
    "builder.add_edge(\"filter\", \"chat_model\")\n",
    "builder.add_edge(\"chat_model\", END)\n",
    "graph = builder.compile()\n",
    "\n",
    "# View\n",
    "display(Image(graph.get_graph().draw_mermaid_png()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "95a7c2cc-54ce-43e7-9a90-abf37827d709",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: Bot\n",
      "\n",
      "So you said you were researching ocean mammals?\n",
      "================================\u001b[1m Human Message \u001b[0m=================================\n",
      "Name: Lance\n",
      "\n",
      "Yes, I know about whales. But what others should I learn about?\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "\n",
      "In addition to whales, there are several other fascinating ocean mammals you might want to learn about:\n",
      "\n",
      "1. **Dolphins**: Highly intelligent and social animals, with various species such as the bottlenose dolphin and the orca (also known as a killer whale, though it is actually a dolphin).\n",
      "\n",
      "2. **Porpoises**: Similar to dolphins but generally smaller and with different facial structures and teeth. Examples include the harbor porpoise and the vaquita, which is critically endangered.\n",
      "\n",
      "3. **Seals**: Semiaquatic marine mammals that are divided into earless seals (true seals) like the harbor seal and eared seals such as sea lions and fur seals.\n",
      "\n",
      "4. **Sea Lions**: Known for their external ear flaps and the ability to walk on land using their flippers. Common species include the California sea lion and the Steller sea lion.\n",
      "\n",
      "5. **Walruses**: Large marine mammals known for their long tusks and whiskers, found mostly in the Arctic region.\n",
      "\n",
      "6. **Manatees**: Often referred to as \"sea cows,\" these gentle giants are herbivorous and typically found in shallow coastal waters and rivers.\n",
      "\n",
      "7. **Dugongs**: Closely related to manatees, they are found in warm coastal waters from East Africa to Australia, including the Red Sea, Indian Ocean, and Pacific Ocean.\n",
      "\n",
      "8. **Sea Otters**: While not as large as other ocean mammals, sea otters are fascinating for their use of tools and role in maintaining coastal ecosystems. They are usually found in the northern and eastern North Pacific Ocean.\n",
      "\n",
      "9. **Polar Bears**: Although mostly land residents, polar bears spend a significant amount of time in the ocean and are excellent swimmers.\n",
      "\n",
      "Learning about these animals can give you a wider understanding of the diversity and ecological importance of marine mammals in ocean environments.\n"
     ]
    }
   ],
   "source": [
    "# Message list with a preamble\n",
    "messages = [AIMessage(\"Hi.\", name=\"Bot\", id=\"1\")]\n",
    "messages.append(HumanMessage(\"Hi.\", name=\"Lance\", id=\"2\"))\n",
    "messages.append(AIMessage(\"So you said you were researching ocean mammals?\", name=\"Bot\", id=\"3\"))\n",
    "messages.append(HumanMessage(\"Yes, I know about whales. But what others should I learn about?\", name=\"Lance\", id=\"4\"))\n",
    "\n",
    "# Invoke\n",
    "output = graph.invoke({'messages': messages})\n",
    "for m in output['messages']:\n",
    "    m.pretty_print()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f506457d-014b-4fee-a684-e5edfb4b8f0d",
   "metadata": {},
   "source": [
    "## Filtering messages\n",
    "\n",
    "If you don't need or want to modify the graph state, you can just filter the messages you pass to the chat model.\n",
    "\n",
    "For example, just pass in a filtered list: `llm.invoke(messages[-1:])` to the model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "22d0b904-7cd6-486b-8948-105bee3d4683",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Node\n",
    "def chat_model_node(state: MessagesState):\n",
    "    return {\"messages\": [llm.invoke(state[\"messages\"][-1:])]}\n",
    "\n",
    "# Build graph\n",
    "builder = StateGraph(MessagesState)\n",
    "builder.add_node(\"chat_model\", chat_model_node)\n",
    "builder.add_edge(START, \"chat_model\")\n",
    "builder.add_edge(\"chat_model\", END)\n",
    "graph = builder.compile()\n",
    "\n",
    "# View\n",
    "display(Image(graph.get_graph().draw_mermaid_png()))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6f58c6fc-532f-418d-b70a-cfcb3307daf5",
   "metadata": {},
   "source": [
    "Let's take our existing list of messages, append the above LLM response, and append a follow-up question."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "16956015-1dbe-4108-89b5-4209b68b51ca",
   "metadata": {},
   "outputs": [],
   "source": [
    "messages.append(output['messages'][-1])\n",
    "messages.append(HumanMessage(f\"Tell me more about Narwhals!\", name=\"Lance\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "85563415-c085-46a8-a4ac-155df798c54e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: Bot\n",
      "\n",
      "Hi.\n",
      "================================\u001b[1m Human Message \u001b[0m=================================\n",
      "Name: Lance\n",
      "\n",
      "Hi.\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: Bot\n",
      "\n",
      "So you said you were researching ocean mammals?\n",
      "================================\u001b[1m Human Message \u001b[0m=================================\n",
      "Name: Lance\n",
      "\n",
      "Yes, I know about whales. But what others should I learn about?\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "\n",
      "In addition to whales, there are several other fascinating ocean mammals you might want to learn about:\n",
      "\n",
      "1. **Dolphins**: Highly intelligent and social animals, with various species such as the bottlenose dolphin and the orca (also known as a killer whale, though it is actually a dolphin).\n",
      "\n",
      "2. **Porpoises**: Similar to dolphins but generally smaller and with different facial structures and teeth. Examples include the harbor porpoise and the vaquita, which is critically endangered.\n",
      "\n",
      "3. **Seals**: Semiaquatic marine mammals that are divided into earless seals (true seals) like the harbor seal and eared seals such as sea lions and fur seals.\n",
      "\n",
      "4. **Sea Lions**: Known for their external ear flaps and the ability to walk on land using their flippers. Common species include the California sea lion and the Steller sea lion.\n",
      "\n",
      "5. **Walruses**: Large marine mammals known for their long tusks and whiskers, found mostly in the Arctic region.\n",
      "\n",
      "6. **Manatees**: Often referred to as \"sea cows,\" these gentle giants are herbivorous and typically found in shallow coastal waters and rivers.\n",
      "\n",
      "7. **Dugongs**: Closely related to manatees, they are found in warm coastal waters from East Africa to Australia, including the Red Sea, Indian Ocean, and Pacific Ocean.\n",
      "\n",
      "8. **Sea Otters**: While not as large as other ocean mammals, sea otters are fascinating for their use of tools and role in maintaining coastal ecosystems. They are usually found in the northern and eastern North Pacific Ocean.\n",
      "\n",
      "9. **Polar Bears**: Although mostly land residents, polar bears spend a significant amount of time in the ocean and are excellent swimmers.\n",
      "\n",
      "Learning about these animals can give you a wider understanding of the diversity and ecological importance of marine mammals in ocean environments.\n",
      "================================\u001b[1m Human Message \u001b[0m=================================\n",
      "Name: Lance\n",
      "\n",
      "Tell me more about Narwhals!\n"
     ]
    }
   ],
   "source": [
    "for m in messages:\n",
    "    m.pretty_print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "23349705-a059-47b5-9760-d8f64e687393",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: Bot\n",
      "\n",
      "Hi.\n",
      "================================\u001b[1m Human Message \u001b[0m=================================\n",
      "Name: Lance\n",
      "\n",
      "Hi.\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "Name: Bot\n",
      "\n",
      "So you said you were researching ocean mammals?\n",
      "================================\u001b[1m Human Message \u001b[0m=================================\n",
      "Name: Lance\n",
      "\n",
      "Yes, I know about whales. But what others should I learn about?\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "\n",
      "In addition to whales, there are several other fascinating ocean mammals you might want to learn about:\n",
      "\n",
      "1. **Dolphins**: Highly intelligent and social animals, with various species such as the bottlenose dolphin and the orca (also known as a killer whale, though it is actually a dolphin).\n",
      "\n",
      "2. **Porpoises**: Similar to dolphins but generally smaller and with different facial structures and teeth. Examples include the harbor porpoise and the vaquita, which is critically endangered.\n",
      "\n",
      "3. **Seals**: Semiaquatic marine mammals that are divided into earless seals (true seals) like the harbor seal and eared seals such as sea lions and fur seals.\n",
      "\n",
      "4. **Sea Lions**: Known for their external ear flaps and the ability to walk on land using their flippers. Common species include the California sea lion and the Steller sea lion.\n",
      "\n",
      "5. **Walruses**: Large marine mammals known for their long tusks and whiskers, found mostly in the Arctic region.\n",
      "\n",
      "6. **Manatees**: Often referred to as \"sea cows,\" these gentle giants are herbivorous and typically found in shallow coastal waters and rivers.\n",
      "\n",
      "7. **Dugongs**: Closely related to manatees, they are found in warm coastal waters from East Africa to Australia, including the Red Sea, Indian Ocean, and Pacific Ocean.\n",
      "\n",
      "8. **Sea Otters**: While not as large as other ocean mammals, sea otters are fascinating for their use of tools and role in maintaining coastal ecosystems. They are usually found in the northern and eastern North Pacific Ocean.\n",
      "\n",
      "9. **Polar Bears**: Although mostly land residents, polar bears spend a significant amount of time in the ocean and are excellent swimmers.\n",
      "\n",
      "Learning about these animals can give you a wider understanding of the diversity and ecological importance of marine mammals in ocean environments.\n",
      "================================\u001b[1m Human Message \u001b[0m=================================\n",
      "Name: Lance\n",
      "\n",
      "Tell me more about Narwhals!\n",
      "==================================\u001b[1m Ai Message \u001b[0m==================================\n",
      "\n",
      "Certainly! Narwhals, known as the \"unicorns of the sea,\" are fascinating marine mammals that are part of the Monodontidae family, which also includes the beluga whale. They are easily recognized by their long, spiral tusk that protrudes from the heads of males, and occasionally females. This tusk is actually an elongated upper-left canine tooth and can grow up to 10 feet (about 3 meters) in length.\n",
      "\n",
      "### Physical Characteristics:\n",
      "- **Size and Weight**: Narwhals can grow up to 16 feet (about 5 meters) long, not including the tusk, and can weigh up to 3,500 pounds (about 1,600 kilograms).\n",
      "- **Coloration**: Their skin is usually mottled black and white, but it can become more white as the narwhal ages.\n",
      "\n",
      "### Habitat:\n",
      "Narwhals inhabit Arctic waters, and they are primarily found in the Atlantic sector of the Arctic Ocean and the waters off northern Canada, Greenland, and Russia. They are known to dive to depths exceeding 4,900 feet (1,500 meters) in search of food, such as fish, squid, and shrimp.\n",
      "\n",
      "### Behavior:\n",
      "- **Social Structure**: Narwhals are social animals and tend to travel in groups called pods, usually consisting of 10 to 20 individuals. However, during the summer, groups can aggregate into large gatherings of several hundred narwhals.\n",
      "- **Communication**: They are known to be vocal animals, using clicks, whistles, and knocks to communicate and navigate the dark Arctic waters using echolocation.\n",
      "\n",
      "### Tusk Function:\n",
      "The exact function of the tusk is not entirely understood, but several theories exist. It may play a role in mating rituals and social dominance, or it might have sensory capabilities, given its thousands of nerve endings, which could help narwhals detect changes in their environment.\n",
      "\n",
      "### Conservation Status:\n",
      "Narwhals face threats from climate change, particularly due to the loss of sea ice habitat, as well as from human activities like shipping, oil, gas exploration, and hunting by indigenous communities. They are currently classified as \"Near Threatened\" by the International Union for Conservation of Nature (IUCN).\n",
      "\n",
      "Narwhals are an iconic symbol of the Arctic and an important part of Indigenous cultures. Their unique characteristics and adaptations make them a subject of interest and study in marine biology and conservation efforts.\n"
     ]
    }
   ],
   "source": [
    "# Invoke, using message filtering\n",
    "output = graph.invoke({'messages': messages})\n",
    "for m in output['messages']:\n",
    "    m.pretty_print()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "42e1d8d2-e297-4d78-b54c-d12b3c866745",
   "metadata": {},
   "source": [
    "The state has all of the mesages.\n",
    "\n",
    "But, let's look at the LangSmith trace to see that the model invocation only uses the last message:\n",
    "\n",
    "https://smith.langchain.com/public/75aca3ce-ef19-4b92-94be-0178c7a660d9/r"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fc40d930-3c1f-47fe-8d2a-ce174873353c",
   "metadata": {},
   "source": [
    "## Trim messages\n",
    "\n",
    "Another approach is to [trim messages](https://python.langchain.com/v0.2/docs/how_to/trim_messages/#getting-the-last-max_tokens-tokens), based upon a set number of tokens. \n",
    "\n",
    "This restricts the message history to a specified number of tokens.\n",
    "\n",
    "While filtering only returns a post-hoc subset of the messages between agents, trimming restricts the number of tokens that a chat model can use to respond.\n",
    "\n",
    "See the `trim_messages` below."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "2ff99b81-cf03-4cc2-b44f-44829a73e1fd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from langchain_core.messages import trim_messages\n",
    "\n",
    "# Node\n",
    "def chat_model_node(state: MessagesState):\n",
    "    messages = trim_messages(\n",
    "            state[\"messages\"],\n",
    "            max_tokens=100,\n",
    "            strategy=\"last\",\n",
    "            token_counter=ChatOpenAI(model=\"gpt-4o\"),\n",
    "            allow_partial=False,\n",
    "        )\n",
    "    return {\"messages\": [llm.invoke(messages)]}\n",
    "\n",
    "# Build graph\n",
    "builder = StateGraph(MessagesState)\n",
    "builder.add_node(\"chat_model\", chat_model_node)\n",
    "builder.add_edge(START, \"chat_model\")\n",
    "builder.add_edge(\"chat_model\", END)\n",
    "graph = builder.compile()\n",
    "\n",
    "# View\n",
    "display(Image(graph.get_graph().draw_mermaid_png()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "24df63ac-da29-4874-b3df-7e390e97cc8a",
   "metadata": {},
   "outputs": [],
   "source": [
    "messages.append(output['messages'][-1])\n",
    "messages.append(HumanMessage(f\"Tell me where Orcas live!\", name=\"Lance\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "6d9d8971-c75c-43ca-a209-eb1d07b2ead0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[HumanMessage(content='Tell me where Orcas live!', additional_kwargs={}, response_metadata={}, name='Lance')]"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Example of trimming messages\n",
    "trim_messages(\n",
    "            messages,\n",
    "            max_tokens=100,\n",
    "            strategy=\"last\",\n",
    "            token_counter=ChatOpenAI(model=\"gpt-4o\"),\n",
    "            allow_partial=False\n",
    "        )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "ed70a269-a869-4fa0-a1df-29736a432c51",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Invoke, using message trimming in the chat_model_node \n",
    "messages_out_trim = graph.invoke({'messages': messages})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "38b3db67-380e-46b5-9a6a-20100ba52008",
   "metadata": {},
   "source": [
    "Let's look at the LangSmith trace to see the model invocation:\n",
    "\n",
    "https://smith.langchain.com/public/b153f7e9-f1a5-4d60-8074-f0d7ab5b42ef/r"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
